﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MSWMDMLib;
using System.Collections.ObjectModel;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
using FireZone.NativeWMDMInteface;
using FireZone.WMDMHelper;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace FireZone.DataStructure
{
    internal struct StorageAttribute
    {
        public WMDM_STORAGE_ATTR dwAttributes;
        public uint dwAttributesEx;
        public _WAVEFORMATEX waveFormat;
        public _VIDEOINFOHEADER videoFormat;
    }
//    public struct StorageGlobal
//    {
//        private ulong? _storageFreeSpace;
//        public ulong? storageFreeSpace
//        {
//            get
//            {
////                if (!_storageFreeSpace.HasValue)
//                {
//                    uint uLow = 0, uHigh = 0;
//                    stgGlobals.GetTotalFree(out uLow, out uHigh);
//                    _storageFreeSpace = (ulong)uLow + ((ulong)uHigh << 32);
//                }
//                return _storageFreeSpace;
//            }
//            set
//            {
//                _storageFreeSpace = value;
//            }
//        }
//        private ulong? _storageTotalSpace;
//        public ulong? storageTotalSpace
//        {
//            get
//            {
////                if (!_storageTotalSpace.HasValue)
//                {
//                    uint uLow = 0, uHigh = 0;
//                    stgGlobals.GetTotalSize(out uLow, out uHigh);
//                    _storageTotalSpace = (ulong)uLow + ((ulong)uHigh << 32);
//                }
//                return _storageTotalSpace;
//            }
//            set
//            {
//                _storageTotalSpace = value;
//            }
//        }
//        public IWMDMStorageGlobals stgGlobals { get; set; }
//    }

    internal class MTPStorageItem : IEquatable<MTPStorageItem>, INotifyPropertyChanged
    {
        public ObservableCollection<MTPStorageItem> ChildStorages
        {
            get
            {
                if (((storageAttribute.Value.dwAttributes & WMDM_STORAGE_ATTR.WMDM_FILE_ATTR_FOLDER) != 0) && (_childStorages == null))
                {
                    WMDMStorageEnum wmdmStgEnum = null;
                    //try
                    //{
                        _childStorages = new ObservableCollection<MTPStorageItem>();
                        //Task.Factory.StartNew(() =>
                        //{
                            StorageItem.EnumStorage(out wmdmStgEnum);
                        //}).Wait();
                        while (true)
                        {
                            WMDMStorage wmdmStg;
                            uint uFetched = 0;
                            wmdmStgEnum.Next(1, out wmdmStg, out uFetched);
                            if (uFetched == 0) break;
                            _childStorages.Add(new MTPStorageItem() { StorageItem = (IWMDMStorage3)wmdmStg, });
                        }
                    //}
                    //catch(COMException)
                    //{
                    //}
                }
                return _childStorages;
            }
        }
        public StorageAttribute? storageAttribute
        {
            get
            {
                if (!_storageAttribute.HasValue)
                {
                    StorageAttribute stgAttribute;
                    StorageItem.GetAttributes2(out stgAttribute.dwAttributes, out  stgAttribute.dwAttributesEx, out stgAttribute.waveFormat, out stgAttribute.videoFormat);
                    _storageAttribute = stgAttribute;
                }
                return _storageAttribute;
            }
            set
            {
                _storageAttribute = value;
            }
        }
        public String StorageName
        {
            get
            {
                if (_storageName == null)
                {
                    StringBuilder strValue = new StringBuilder(1024);
                    StorageItem.GetName(strValue, (uint)strValue.Capacity);
                    _storageName = strValue.ToString();
                }
                return _storageName;
            }
            set
            {
                _storageName = value;
            }
        }
        public DateTime? StorageDate
        {
            get
            {
                if (!_storageDate.HasValue)
                {
                    _WMDMDATETIME wmdmDate;
                    StorageItem.GetDate(out wmdmDate);
                    _storageDate = new DateTime(wmdmDate.wYear, wmdmDate.wMonth, wmdmDate.wDay, wmdmDate.wHour, wmdmDate.wMinute, wmdmDate.wSecond);
                }
                return _storageDate;
            }
            set
            {
                _storageDate = value;
            }
        }
        public ulong? StorageSize
        {
            get
            {
                if (!_storageSize.HasValue)
                {
                    uint uLow = 0, uHigh = 0;
                    StorageItem.GetSize(out uLow, out uHigh);
                    _storageSize = (ulong)uLow + ((ulong)uHigh << 32);
                }
                return _storageSize;
            }
        }
        private ObservableCollection<MTPStorageItem> _childStorages;
        private StorageAttribute? _storageAttribute;
        private string _storageName;
        private DateTime? _storageDate;
        private ulong? _storageSize;
        private ulong? _storageTotalSpace;
        private ulong? _storageFreeSpace;

        public ulong? StorageUsedSpace
        {
            get
            {
                if (!_storageTotalSpace.HasValue) this.SafeInvalidateStorageGlobal();
                return _storageTotalSpace - _storageFreeSpace;
            }
        }
        public ulong? StorageTotalSpace 
        { 
            get
            {
                if (!_storageTotalSpace.HasValue) this.SafeInvalidateStorageGlobal();
                return _storageTotalSpace;
            }
            set
            {
                if(_storageTotalSpace != value)
                {
                    _storageTotalSpace = value;
                    PropertyChanged.NotifyPropertyChangedAsync(this, "StorageTotalSpace");
                }
            }
        }
        public ulong? StorageFreeSpace 
        { 
            get
            {
                if (!_storageFreeSpace.HasValue) this.SafeInvalidateStorageGlobal();
                return _storageFreeSpace;
            }
            set
            {
                if(_storageFreeSpace != value)
                {
                    _storageFreeSpace = value;
                    PropertyChanged.NotifyPropertyChangedAsync(this, "StorageFreeSpace", "StorageUsedSpace");
                }
            }
        }

        public ObservableCollection<MTPPredefinedStorageItem> predefineStorageList
        {
            get
            {
                return new ObservableCollection<MTPPredefinedStorageItem>()
                {
                    new MTPPredefinedStorageItem (){ PredefinedName = "Video", PredefinedStorageName = "Videos", FileExtensions = VideoItem.FileExtensions, StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("Videos"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "Audio", PredefinedStorageName = "Audios", FileExtensions = MusicItem.FileExtensions, StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("Audios"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "Picture", PredefinedStorageName = "Pictures", FileExtensions = PhotoItem.FileExtensions, StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("Pictures");}), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "PowerPoint", PredefinedStorageName = "PowerPoints", FileExtensions = PowerPointItem.FileExtensions, StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("PowerPoints"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "Flash", PredefinedStorageName = "Flashes", FileExtensions = FlashItem.FileExtensions, StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("Flashes"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "HTML", PredefinedStorageName = "HTMLs", FileExtensions = HtmlItem.FileExtensions, StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("HTMLs"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "Playlist", PredefinedStorageName = "Playlists", FileExtensions = PlaylistItem.FileExtensions, StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("Playlists"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "Subtitle", PredefinedStorageName = "Subtitles", StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("Subtitles"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "System", PredefinedStorageName = "System", StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("System"); }), },
                    new MTPPredefinedStorageItem (){ PredefinedName = "Bookmark", PredefinedStorageName = "Bookmarks", StorageItem = new Lazy<MTPStorageItem>(()=>{ return this.SafeGetChildFolderStorageItem("Bookmarks"); }), },
                 };                
            }
        }
        public MTPStorageItem this[int i]
        {
            get
            {
                switch (i)
                {
                    case 0:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "Videos"); });
                    case 1:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "Audios"); });
                    case 2:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "Pictures"); });
                    case 3:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "Flashes"); });
                    case 4:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "PowerPoints"); });
                    case 5:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "HTMLs"); });
                    case 6:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "Playlists"); });
                    case 7:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "Subtitles"); });
                    case 8:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "System"); });
                    case 9:
                        return ChildStorages.FirstOrDefault((n) => { return (n.StorageName == "Bookmarks"); });
                    default:
                        throw new IndexOutOfRangeException();
                }

            }
        }
        public String preferStorageName
        {
            get;
            set;
        }

        public IWMDMStorage3 StorageItem
        {
            get;
            set;
        }

        public static IDictionary<string, WMDM_FORMATCODE> FileExtensions
        {
            get;
            set;
        }
        public static IDictionary<PropertyKey, string> VisibleColumns
        {
            get;
            set;
        }

        #region IEquatable<MTPStorageItem> Members

        public bool Equals(MTPStorageItem other)
        {
            return StorageName.Equals(other.StorageName, StringComparison.OrdinalIgnoreCase);
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private IWMDMStorage3 _storageItem;
        private ulong? _storageUsedSpace;

        #endregion
    }


    internal class PowerSource
    {
        public WMDMPowerSource devicePowerSource { get; set; }
        public uint devicePowerPercentRemaining { get; set; }
    }
}
